package org.epanetgrid.otimizacao.searchspace;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.epanetgrid.otimizacao.simulation.SimulacaoNaoConvergeException;
import org.jheuristics.Individual;


/**
 * Implementa��o default de BulkIndividualEvaluator. Para todos os indiv�duos passados, o evaluator
 * retorna o objeto relacionado correspondente, retornando assim a lista com os indiv�duos "evoluidos".
 * Tem como diferencial do SimpleBulkIndividualEvaluator que caso o indiv�duo j� tenha sido rodado anteriormente, 
 * o resultado ser� retornado a partir do Mapa  
 * 
 * @author vinicius
 *
 */
public class SimpleWithMapBulkIndividualEvaluator implements BulkIndividualEvaluator, Serializable {
	/**
	 * 
	 */
	private static final long serialVersionUID = 4728951558045211359L;
	private IndividualEvaluator evaluator;
	private Map<Object, Individual> individualsSimulados;

	/**
	 * @param evaluator Evaluator que analizar� os indiv�duos passados
	 */
	public SimpleWithMapBulkIndividualEvaluator(IndividualEvaluator evaluator) {
		if (null == evaluator) {
			// TODO: ERROR MSG
			throw new NullPointerException();
		}
		this.evaluator = evaluator;
		individualsSimulados = new HashMap<Object, Individual>();
	}

	/* (non-Javadoc)
	 * @see org.smartpumping.otimizacao.searchspace.BulkIndividualEvaluator#evaluate(java.util.List)
	 */
	public List evaluate(List individuals) {
		for (Iterator it = individuals.iterator(); it.hasNext(); ) {
			if (!(it.next() instanceof Individual)) {
				throw new IllegalArgumentException();
			}
		}
		List result = new LinkedList();
		for (Iterator it = individuals.iterator(); it.hasNext(); ) {
			Individual tmp = (Individual) it.next();
			if (null == individualsSimulados.get(tmp.getGens())) {
				Individual simulated = null;
				try {
					simulated = evaluator.evaluate(tmp);
				}catch (SimulacaoNaoConvergeException e) {
				}
				//adiciona o tmp mesmo, pois nao teve o dataApplicationSetado
				individualsSimulados.put(tmp.getGens(), simulated == null? tmp:simulated);
			}
			result.add(individualsSimulados.get(tmp.getGens()));
		}
		return result;
	}
	
}
